import re
from tagengine.commons import *
import logging
import os.path
import sqlite3

logger = logging.getLogger("tagengine.parsers.languageparser")
FILE_LOCATION = os.path.dirname(os.path.realpath(__file__))


class CommandRulesRetriever:
    def __init__(self, rulefiles=[]):
        self.rulefiles = [os.path.join(FILE_LOCATION, "languagedefault.db")] + rulefiles
        self.rules = {}
        self.aliases = {}
        
        for filename in self.rulefiles:
            rules, aliases = CommandRulesRetriever.getRules(filename)
            self.rules.update(rules)
            self.aliases.update(aliases)
        
        self.buildPatterns()
        
        for uniqueid in self.rules:
            for i in xrange(len(self.rules[uniqueid]["regex"])):
                self.rules[uniqueid]["regex"][i][0] = self.processRegex(self.rules[uniqueid]["regex"][i][0])
        
            
    def buildPatterns(self):      
        verbs = ""
        for key in self.aliases:
            verbs += key + "|"
        
        verbs = verbs[:-1]
        verbs = "(" + verbs + ")"
        
        preps = "(with|to|as|in|on)"
        
        self.verbPattern = "(?P<verb>%s)" % verbs
        self.objectPattern = "(?P<object>\W+\w+\W*?\w*?|\Z)"
        self.prepPattern = "(?P<prep>\W+%s|\Z)" % preps
        self.indirectObjectPattern = "(?P<indirectobject>\W+\w+\W*\w*|\Z)"
        
        self.generalPattern = self.processRegex(r"^<\verb\><\object\><\prep\><\indirectobject\>$")
        
    @staticmethod
    def getRules(filename):
        conn = sqlite3.connect(filename)
        c = conn.cursor()
        c.execute("SELECT uniqueid, regex, class, function, aliases FROM commands")
        rules = {}
        aliases = {}
        for row in c:
            regex = row[1]
            if not regex:
                regex = "[]"
            
            rule = {
                    "regex" : eval(regex),
                    "class" : row[2].split(";"),
                    "function" : row[3].split(";") 
                    }
            
            logger.debug("Processed Rules: %s " % str(rule))
            
            rules[row[0]] = rule
            
            singleVerbAliases = row[4].split(";")
            for a in singleVerbAliases:
                temp = aliases.get(a, [])
                temp.append(row[0])
                aliases[a] = temp
                
        
        logger.debug("Processed Aliases: %s" % str(aliases))
            
        return rules, aliases
    
    def processRegex(self, regex):
        regex = regex.replace(r"<\verb\>", self.verbPattern)
        regex = regex.replace(r"<\object\>", self.objectPattern)
        regex = regex.replace(r"<\prep\>", self.prepPattern)
        regex = regex.replace(r"<\indirectobject\>", self.indirectObjectPattern)
        logger.debug("Processed Regex: " + regex)
        regex = re.compile(regex)
            
        return regex
        
# Regex Explanation
# (?P<verb>%s)               - ?P<verb> is used for the group() function
#                            - %s is being replaced by the variable verb. Which would be a verb
#                            - This is a required word
# (?<object>\W+\w+\W*?\w*?|\Z) - \W+ means 1 or more space. This comes right after the verb
#                            - \w+ means 1 or more characters. This is the object word
#                            - \W*? means 0 or more space. This comes in handy when the item is being described with 2 word (red pen), this matches the space beteen the 2 words.
#                            - \w*? means 0 or more characters. This is the second optional object word. ? makes it non-greedy, so it won't match a preposition as part of the object.
#                            - |\Z means or the end of string, so things like "look", with verb only can be matched.
# The clause for the indirectobj is the same as the object's regex.
